/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.service.core.impl;

import com.blandware.atleap.common.util.PartialCollection;
import com.blandware.atleap.common.util.QueryInfo;
import com.blandware.atleap.model.core.*;
import com.blandware.atleap.persistence.core.ContentDocumentDAO;
import com.blandware.atleap.persistence.core.ContentImageDAO;
import com.blandware.atleap.persistence.core.ContentLocaleDAO;
import com.blandware.atleap.persistence.core.ContentResourceDAO;
import com.blandware.atleap.persistence.exception.DeleteException;
import com.blandware.atleap.service.core.ContentResourceManager;
import com.blandware.atleap.service.core.UtilManager;
import com.blandware.atleap.service.exception.BeanAlreadyExistsException;
import com.blandware.atleap.service.exception.BeanNotFoundException;
import com.blandware.atleap.service.exception.ContentLocaleNotFoundException;

import java.util.List;

/**
 * <p>Implementation of ContentResourceManager</p>
 * <p><a href="ContentResourceManagerImpl.java.html"><i>View Source</i></a>
 * </p>
 *
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @author Andrey Grebnev <a href="mailto:andrey.grebnev@blandware.com">&lt;andrey.grebnev@blandware.com&gt;</a>
 * @version $Revision: 1.20 $ $Date: 2008/01/14 10:59:48 $
 */
public class ContentResourceManagerImpl extends BaseManagerImpl implements ContentResourceManager {

    /**
     * Content resource DAO
     */
	protected ContentResourceDAO contentResourceDAO;
    /**
     * Content image DAO
     */
    protected ContentImageDAO contentImageDAO;
    /**
     * Content document DAO
     */
    protected ContentDocumentDAO contentDocumentDAO;
    /**
     * Content locale DAO
     */
    protected ContentLocaleDAO contentLocaleDAO;

    /**
     * Util manager to use
     */
    protected UtilManager utilManager;

	/**
	 * Creates new instance of ContentResourceManagerImpl
	 */
	public ContentResourceManagerImpl() {
	}

    /**
     * Sets DAO for operating with content resources
     *
     * @param contentResourceDAO the DAO to set
     */
	public void setContentResourceDAO(ContentResourceDAO contentResourceDAO) {
		this.contentResourceDAO = contentResourceDAO;
	}

    /**
     * Sets DAO for operating with content images
     *
     * @param contentImageDAO the DAO to set
     */
    public void setContentImageDAO(ContentImageDAO contentImageDAO) {
        this.contentImageDAO = contentImageDAO;
    }

    /**
     * Sets DAO for operating with content documents
     *
     * @param contentDocumentDAO the DAO to set
     */
    public void setContentDocumentDAO(ContentDocumentDAO contentDocumentDAO) {
        this.contentDocumentDAO = contentDocumentDAO;
    }

    /**
     * Sets DAO for operating with content locales
     *
     * @param contentLocaleDAO the DAO to set
     */
    public void setContentLocaleDAO(ContentLocaleDAO contentLocaleDAO) {
        this.contentLocaleDAO = contentLocaleDAO;
    }

    /**
     * Sets util manager to use
     *
     * @param utilManager manager to set
     */
    public void setUtilManager(UtilManager utilManager) {
        this.utilManager = utilManager;
    }


	// C O N T E N T    R E S O U R C E S


	//~ CRUD Methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#createContentResource(com.blandware.atleap.model.core.ContentResource, com.blandware.atleap.model.core.ResourceData)
	 */
	public Long createContentResource(ContentResource contentResource, ResourceData resourceData) throws BeanAlreadyExistsException {

		if ( log.isDebugEnabled() ) {
			log.debug("Creating new content resource (uri=" + contentResource.getUri() + ")...");
		}

		Long contentResourceId;

		if ( contentResourceDAO.hasDuplicates(contentResource) ) {
			throw new BeanAlreadyExistsException("Content resource with the same URI already exists");
		}

		// resource does not exist, create it
		contentResourceId = contentResourceDAO.createContentResource(contentResource, resourceData);


		if ( log.isDebugEnabled() ) {
			log.debug("New resource has been created succefully. It's ID is " + contentResourceId);
		}

		return contentResourceId;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#retrieveContentResource(java.lang.Long)
	 */
	public ContentResource retrieveContentResource(Long contentResourceId) {
		return contentResourceDAO.retrieveContentResource(contentResourceId);
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#updateContentResource(com.blandware.atleap.model.core.ContentResource, com.blandware.atleap.model.core.ResourceData)
	 */
	public void updateContentResource(ContentResource contentResource, ResourceData resourceData) throws BeanAlreadyExistsException {
        // remove resource from cache in order to prevent Hibernate from assigning new version number
		contentResourceDAO.removeFromCache(contentResource);

		if ( log.isDebugEnabled() ) {
			log.debug("Updating content resource (uri=" + contentResource.getUri() + ")...");
		}

		if ( contentResourceDAO.hasDuplicates(contentResource) ) {
			throw new BeanAlreadyExistsException("Content resource with the same URI already exists");
		}

		// resource with this URI does not exist, so update it
        ContentResource oldResource = contentResourceDAO.retrieveContentResource(contentResource.getId());
        if (oldResource != null) {
            String oldUri = oldResource.getUri();
            String newUri = contentResource.getUri();
            if (!newUri.equals(oldUri)) {
                utilManager.replaceLinkableObjectUriInLinkedObjects(oldUri, newUri, oldResource.getLinkedContentFieldValues(), oldResource.getLinkedMenuItems(), "", true);
            }
            contentResourceDAO.removeFromCache(oldResource);
        }

		contentResourceDAO.updateContentResource(contentResource, resourceData);


		if ( log.isDebugEnabled() ) {
			log.debug("Resource was updated succefully.");
		}
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#deleteContentResource(java.lang.Long)
	 */
	public void deleteContentResource(Long contentResourceId) throws DeleteException, BeanNotFoundException {
		ContentResource contentResource = contentResourceDAO.retrieveContentResource(contentResourceId);
		if ( contentResource == null ) {
			String errorMessage = "No content resource with ID=" + contentResource + "could be found";
			throw new BeanNotFoundException(errorMessage);
		}

		contentResourceDAO.deleteContentResource(contentResource);
	}

	// ~ Additional methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#listContentResources(com.blandware.atleap.common.util.QueryInfo)
	 */
	public PartialCollection listContentResources(QueryInfo queryInfo) {
		return contentResourceDAO.listContentResources(queryInfo);
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#getLastContentResources(com.blandware.atleap.common.util.QueryInfo) 
	 */
    public List getLastContentResources(QueryInfo queryInfo) {
        return contentResourceDAO.getLastContentResources(queryInfo);
    }

    /**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#increaseUsageCounter(java.lang.Long, java.lang.Integer)
	 */
	public void increaseUsageCounter(Long resourceId, Integer value) throws BeanNotFoundException {
		ContentResource resource = contentResourceDAO.retrieveContentResource(resourceId);

		if ( resource == null ) {
			// resource does not exist
			String errorMessage = "Resource with ID=" + resourceId + " does not exist";
			if ( log.isErrorEnabled() ) {
				log.error(errorMessage);
			}
			throw new BeanNotFoundException(errorMessage);
		}

		resource.setUsageCounter(new Integer(resource.getUsageCounter().intValue() + value.intValue()));
		contentResourceDAO.updateContentResource(resource, resource.getResourceData());
	}

	// ~ Finders ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#listContentResources(com.blandware.atleap.common.util.QueryInfo)
	 */
	public ContentResource findContentResourceByUri(String uri) {
		return contentResourceDAO.findContentResourceByUri(uri);
	}

	// C O N T E N T    I M A G E S


	//~ CRUD Methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#createContentImage(com.blandware.atleap.model.core.ContentImage, com.blandware.atleap.model.core.ResourceData)
	 */
	public Long createContentImage(ContentImage contentImage, ResourceData resourceData) throws BeanAlreadyExistsException {

		if ( log.isDebugEnabled() ) {
			log.debug("Creating new content image (uri=" + contentImage.getUri() + ")...");
		}

		Long contentImageId;
		if ( contentResourceDAO.hasDuplicates(contentImage) ) {
			throw new BeanAlreadyExistsException("Content image with the same URI already exists");
		}


		// image does not exist, create it
		contentImageId = contentImageDAO.createContentImage(contentImage, resourceData);


		if ( log.isDebugEnabled() ) {
			log.debug("New image has been created succefully. It's ID is " + contentImageId);
		}

		return contentImageId;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#retrieveContentImage(java.lang.Long)
	 */
	public ContentImage retrieveContentImage(Long contentImageId) {
		ContentImage contentImage;
		contentImage = contentImageDAO.retrieveContentImage(contentImageId);
		return contentImage;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#updateContentImage(com.blandware.atleap.model.core.ContentImage, com.blandware.atleap.model.core.ResourceData)
	 */
	public void updateContentImage(ContentImage contentImage, ResourceData resourceData) throws BeanAlreadyExistsException {
        // remove content image from cache in order to prevent Hibernate from assigning new version number
		contentImageDAO.removeFromCache(contentImage);
		if ( log.isDebugEnabled() ) {
			log.debug("Updating content image (uri=" + contentImage.getUri() + ")...");
		}

		if ( contentResourceDAO.hasDuplicates(contentImage) ) {
			throw new BeanAlreadyExistsException("Content image with the same URI already exists");
		}

		// image with this URI does not exist, so update it
        ContentImage oldImage = (ContentImage) contentResourceDAO.retrieveContentResource(contentImage.getId());
        if (oldImage != null) {
            String oldUri = oldImage.getUri();
            int oldWidth = oldImage.getWidth().intValue();
            int oldHeight = oldImage.getHeight().intValue();
            String newUri = contentImage.getUri();
            int newWidth = contentImage.getWidth().intValue();
            int newHeight = contentImage.getHeight().intValue();
            if (newWidth != oldWidth || newHeight != oldHeight) {
                utilManager.replaceImageSizesInLinkedObjects(oldUri, oldImage.getLinkedContentFieldValues(), oldWidth, oldHeight, newWidth, newHeight, "", true);
            }
            if (!newUri.equals(oldUri)) {
                utilManager.replaceLinkableObjectUriInLinkedObjects(oldUri, newUri, oldImage.getLinkedContentFieldValues(), oldImage.getLinkedMenuItems(), "", true);
            }
            contentResourceDAO.removeFromCache(oldImage);
        }

		contentImageDAO.updateContentImage(contentImage, resourceData);


		if ( log.isDebugEnabled() ) {
			log.debug("Image was updated succefully.");
		}
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#deleteContentImage(java.lang.Long)
	 */
	public void deleteContentImage(Long contentImageId) throws DeleteException, BeanNotFoundException {

		ContentImage contentImage = contentImageDAO.retrieveContentImage(contentImageId);
		if ( contentImage == null ) {
			String errorMessage = "No content image with ID=" + contentImage + "could be found";
			throw new BeanNotFoundException(errorMessage);
		}

		contentImageDAO.deleteContentImage(contentImage);
	}

	// ~ Additional methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#listContentImages(com.blandware.atleap.common.util.QueryInfo)
	 */
	public PartialCollection listContentImages(QueryInfo queryInfo) {
		return contentImageDAO.listContentImages(queryInfo);
	}

	// ~ Finders ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentResourceManager#listContentImages(com.blandware.atleap.common.util.QueryInfo)
	 */
	public ContentImage findContentImageByUri(String uri) {
		return contentImageDAO.findContentImageByUri(uri);
	}



    // C O N T E N T    D O C U M E N T S

    //~ CRUD Methods ================================================================

    /**
     * @see com.blandware.atleap.service.core.ContentResourceManager#createContentDocument(com.blandware.atleap.model.core.ContentDocument, com.blandware.atleap.model.core.ResourceData, java.lang.String)
     */
    public Long createContentDocument(ContentDocument contentDocument, ResourceData resourceData, String localeIdentifier) throws ContentLocaleNotFoundException, BeanAlreadyExistsException {

        if ( log.isDebugEnabled() ) {
            log.debug("Creating new content document (uri=" + contentDocument.getUri() + ")...");
        }

        Long contentDocumentId;
        if ( contentResourceDAO.hasDuplicates(contentDocument) ) {
            throw new BeanAlreadyExistsException("Content document with the same URI already exists");
        }

        ContentLocale contentLocale;
        contentLocale = contentLocaleDAO.retrieveContentLocale(localeIdentifier);

        if ( contentLocale == null ) {
            String errorMessage = "No content locale with identifier=" + localeIdentifier + "could be found";
            if ( log.isErrorEnabled() ) {
                log.error(errorMessage);
            }
            throw new ContentLocaleNotFoundException(errorMessage);
        }


        // document does not exist, create it
        contentDocumentId = contentDocumentDAO.createContentDocument(contentDocument, resourceData, contentLocale);


        if ( log.isDebugEnabled() ) {
            log.debug("New document has been created succefully. It's ID is " + contentDocumentId);
        }

        return contentDocumentId;
    }

    /**
     * @see com.blandware.atleap.service.core.ContentResourceManager#retrieveContentDocument(java.lang.Long)
     */
    public ContentDocument retrieveContentDocument(Long contentDocumentId) {
        ContentDocument contentDocument;
        contentDocument = contentDocumentDAO.retrieveContentDocument(contentDocumentId);
        return contentDocument;
    }

    /**
     * @see com.blandware.atleap.service.core.ContentResourceManager#updateContentDocument(com.blandware.atleap.model.core.ContentDocument, com.blandware.atleap.model.core.ResourceData, java.lang.String)
     */
    public void updateContentDocument(ContentDocument contentDocument, ResourceData resourceData, String localeIdentifier) throws ContentLocaleNotFoundException, BeanAlreadyExistsException {
        // remove content document from cache in order to prevent Hibernate from assigning new version number
        contentDocumentDAO.removeFromCache(contentDocument);
        if ( log.isDebugEnabled() ) {
            log.debug("Updating content document (uri=" + contentDocument.getUri() + ")...");
        }

        if ( contentResourceDAO.hasDuplicates(contentDocument) ) {
            throw new BeanAlreadyExistsException("Content document with the same URI already exists");
        }

        ContentLocale contentLocale;
        contentLocale = contentLocaleDAO.retrieveContentLocale(localeIdentifier);
        if ( contentLocale == null ) {
            String errorMessage = "No content locale with identifier=" + localeIdentifier + "could be found";
            if ( log.isErrorEnabled() ) {
                log.error(errorMessage);
            }
            throw new ContentLocaleNotFoundException(errorMessage);
        }

        // document with this URI does not exist, so update it
        ContentResource oldResource = contentResourceDAO.retrieveContentResource(contentDocument.getId());
        if (oldResource != null) {
            String oldUri = oldResource.getUri();
            String newUri = contentDocument.getUri();
            if (!newUri.equals(oldUri)) {
                utilManager.replaceLinkableObjectUriInLinkedObjects(oldUri, newUri, oldResource.getLinkedContentFieldValues(), oldResource.getLinkedMenuItems(), "", true);
            }
            contentResourceDAO.removeFromCache(oldResource);
        }

        contentDocumentDAO.updateContentDocument(contentDocument, resourceData, contentLocale);


        if ( log.isDebugEnabled() ) {
            log.debug("Document was updated succefully.");
        }
    }

    /**
     * @see com.blandware.atleap.service.core.ContentResourceManager#deleteContentDocument(java.lang.Long)
     */
    public void deleteContentDocument(Long contentDocumentId) throws DeleteException, BeanNotFoundException {

        ContentDocument contentDocument = contentDocumentDAO.retrieveContentDocument(contentDocumentId);
        if ( contentDocument == null ) {
            String errorMessage = "No content document with ID=" + contentDocument + "could be found";
            throw new BeanNotFoundException(errorMessage);
        }

        contentDocumentDAO.deleteContentDocument(contentDocument);
    }

    // ~ Additional methods ================================================================

    /**
     * @see com.blandware.atleap.service.core.ContentResourceManager#listContentDocuments(com.blandware.atleap.common.util.QueryInfo)
     */
    public PartialCollection listContentDocuments(QueryInfo queryInfo) {
        return contentDocumentDAO.listContentDocuments(queryInfo);
    }

    // ~ Finders ================================================================

    /**
     * @see com.blandware.atleap.service.core.ContentResourceManager#listContentDocuments(com.blandware.atleap.common.util.QueryInfo)
     */
    public ContentDocument findContentDocumentByUri(String uri) {
        return contentDocumentDAO.findContentDocumentByUri(uri);
    }

}
